package arkham.data.util;

import java.util.Random;

import arkham.util.XmlTools;

public class AmountParser
{
	public enum SpecialAmountType
	{
		NONE,
		ALL,
		HALF, // half round down
		HALF_UP, // half round up
		DOUBLE, // double
		SPLIT, // only for stamina/sanity splits
		STAMINA, // equal stamina
		SANITY, // equal sanity
		SUCCESSES,
		INVALID;
	}

	public int n, m;
	public SpecialAmountType type;

	public AmountParser(String amtStr)
	{
		n = m = 0;
		type = SpecialAmountType.NONE;
		if (amtStr == null)
		{
		    type = SpecialAmountType.INVALID;
		    return;
		}
		if (XmlTools.isNumeric(amtStr))
		{
			n = m = Integer.parseInt(amtStr);
			type = SpecialAmountType.NONE;
		}
		else
		{
			if (amtStr.indexOf('d') != -1)
			{
				// x amount of y-sided dice
				String[] tokens = amtStr.substring(1).split("d");
				int nd = Integer.parseInt(tokens[0]);
				int ns = Integer.parseInt(tokens[1]);
				Random rng = new Random();
				for (int i = 0; i < nd; i++)
				{
					n += (1 + rng.nextInt(ns));
				}
				m = n;
				type = SpecialAmountType.NONE;
			}
			else if (amtStr.indexOf('C') != -1)
			{
				String[] tokens = amtStr.substring(1).split("C");
				n = Integer.parseInt(tokens[0]);
				m = Integer.parseInt(tokens[1]);
				type = SpecialAmountType.NONE;
			}
			else if (amtStr.indexOf('/') != -1)
			{
				String[] tokens = amtStr.substring(1).split("/");
				n = Integer.parseInt(tokens[0]);
				m = Integer.parseInt(tokens[1]);
				type = SpecialAmountType.SPLIT;
			}
			else if (amtStr.equals("=Stam"))
			{
				type = SpecialAmountType.STAMINA;
			}
			else if (amtStr.equals("=San"))
			{
				type = SpecialAmountType.SANITY;
			}
			else if (amtStr.equals("=All"))
			{
				type = SpecialAmountType.ALL;
			}
			else if (amtStr.equals("=Half"))
			{
				type = SpecialAmountType.HALF;
			}
			else if (amtStr.equals("=Dbl"))
			{
				type = SpecialAmountType.DOUBLE;
			}
			else if (amtStr.equals("=HalfUp"))
			{
				type = SpecialAmountType.HALF_UP;
			}
			else if (amtStr.startsWith("=S*"))
			{
				type = SpecialAmountType.SUCCESSES;
				n = m = Integer.parseInt(amtStr.substring(3));
			}
			else
			{
			    type = SpecialAmountType.INVALID;
			}
		}
	}

	/**
	 * Calculates the amount of the value based on the relevant type given to the
	 * amount parser. Note, only None, =Half, =HalfUp and =All have any
	 * effect, otherwise this method returns 0.
	 * @param value the value of interest
	 * @return the result of applying the amount parser on the value
	 */
	public int getNumericAmount(int value)
	{
		switch (type)
		{
		case NONE:
			return n;
		case HALF:
			return value / 2;
		case HALF_UP:
			return (value + 1) / 2;
		case ALL:
			return value;
		default:
			return 0;
		}
	}
}
